Skip to content

Conversation

@Cody-G
Copy link
Contributor

@Cody-G Cody-G commented Feb 8, 2020

…ly when decode_responses=True

Pull Request check-list

Please make sure to review and check all of these items:

  • Does $ tox pass with this change (including linting)?
  • Does travis tests pass with this change (enable it first in your forked repo and wait for the travis build to finish)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?

Description of change

Supports passing memoryviews to redis-py as first outlined in #1265 and discussed further in #1266

@codecov-io
Copy link

codecov-io commented Feb 9, 2020

Codecov Report

Merging #1285 into master will increase coverage by 0.26%.
The diff coverage is 97.91%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1285      +/-   ##
==========================================
+ Coverage   92.45%   92.72%   +0.26%     
==========================================
  Files          19       19              
  Lines        6415     6444      +29     
==========================================
+ Hits         5931     5975      +44     
+ Misses        484      469      -15
Impacted Files Coverage Δ
tests/test_encoding.py 97.59% <100%> (+1.59%) ⬆️
tests/test_pipeline.py 100% <100%> (ø) ⬆️
redis/connection.py 82.02% <90%> (+1.31%) ⬆️
tests/conftest.py 97.53% <0%> (-2.47%) ⬇️
tests/test_monitor.py 100% <0%> (ø) ⬆️
tests/test_commands.py 99.94% <0%> (ø) ⬆️
redis/client.py 86.09% <0%> (+0.28%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3d8d523...5750b4c. Read the comment docs.

Copy link
Contributor

@andymccurdy andymccurdy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some suggestions and questions inline below. And two suggestions overall:

It would be nice to add a simple memoryview test going through a pipeline. The changes to Connection.pack_commands aren't tested otherwise as Pipeline is the only thing calling pack_commands().

Further, I'd propose that we subclass memoryview and override its tobytes() to emit a warning. Then we could use that subclass in the test suite instead of the base memoryview. That should hopefully confirm that these optimizations are actually useful.

value = value.decode(self.encoding, self.encoding_errors)
"Return a unicode string from the bytes-like representation"
if (self.decode_responses or force):
if isinstance(value, memoryview):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you run into a case where you needed this? Are we ever actually decoding memoryview instances?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I ran into a case in the tests where a memoryview gets decoded. I think I got a bit spooked by lines like this and this, but on a closer look those lines shouldn't cause a problem unless the user passes a memoryview kwarg -- and the docs instruct them to pass strings. Maybe it just felt right to make sure that decode(encode(x)) always works, but it seems it's not essential, happy to remove this if you prefer.

@Cody-G
Copy link
Contributor Author

Cody-G commented Feb 16, 2020

Thanks for the review! I think most of the changes are straightforward. I like the idea of subclassing memoryview, but I found out that's not possible. Quoting from the docs: "It is not currently allowed to create subclasses of memoryview." So I think we can't use a custom class to test that we're never calling tobytes(), since the code relies on isinstance(x, memoryview). What we really care about is whether the argument is still a memoryview by the time it gets sent over the socket by sendall here, so testing the return value of pack_command() should be sufficient (it gets called here).

Edit: and also testing pack_commands by using a pipeline as was suggested in the review.

@Cody-G Cody-G requested a review from andymccurdy February 16, 2020 02:44
@Cody-G
Copy link
Contributor Author

Cody-G commented Feb 16, 2020

This seems ready for another review. To summarize the changes, everything was straightforward except:

  • I couldn't subclass memoryview to make a warning-emitting view. But I think the tests to pack_command and pack_commands are sufficient to test that tobytes() doesn't get called (i.e. that we're saving a memory copy)
  • It's undecided whether we should allow Encoder.decode to work with memoryviews (see my comment for details).

I also noticed that the argument length-checking and joining code in pack_commands is redundant with that of pack_command. pack_commands always calls pack_command and they process arguments in the same way. It's probably safe to remove the checking from pack_commands, but I haven't done so in this PR.

@andymccurdy
Copy link
Contributor

Thanks @Cody-G. This has been merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants